/*
 * @Author: 0x9DEFA478
 * @Date: 2025-08-03 19:44:31
 * @LastEditTime: 2025-09-15 23:05:05
 * @LastEditors: 0x9DEFA478
 * @Description: 
 * 
 */
#include "HMakeDependencyItem_Instance.hpp"
#include "SystemProcessAuto.hpp"
#include "HMakePath.hpp"
#include "Tree/H_Tree_AVL.hpp"
#include "SystemUtility/C_VirtualTerminal_Macro.h"
#include "SystemUtility/C_LocalUTF8.hpp"
#include "SystemUtility/C_iostream.hpp"




using namespace std::literals::string_literals;

namespace HMake{


  DependencyItem_TargetPath::DependencyItem_TargetPath(const std::string& TargetPath)noexcept:targetPath(TargetPath){}
  
  DependencyItem_TargetPath::~DependencyItem_TargetPath()noexcept{}

  std::pair<bool,uint64_t> DependencyItem_TargetPath::TargetStatus(){
    return FileGetLastUpdateTime(targetPath);
  }


  DependencyItem_Mark::DependencyItem_Mark(const std::string& TargetPath,Log::Pointer log)noexcept:DependencyItem_TargetPath(TargetPath),log(log){}
  
  DependencyItem_Mark::~DependencyItem_Mark()noexcept{
  }

  int DependencyItem_Mark::Run(){
    auto r=FileUpdateEmpty(targetPath);
    if(r.first!=0){
      log->WriteLog(targetPath+"更新\e[" C_VT_F_Red "m失败\e[0m:"+r.second,Log::Type::Default);
    }
    return r.first;
  }

  void DependencyItem_Mark::DoneEvent(bool IsUpdate){
    if(IsUpdate){
      log->WriteLog("",Log::Type::TaskDone);
    }else{
      log->WriteLog("",Log::Type::TaskDoneSkip);
    }
  }


  DependencyItem_Input::DependencyItem_Input(const std::string& TargetPath)noexcept:DependencyItem_TargetPath(TargetPath){
    isIntoCount=false;
  }
  
  DependencyItem_Input::~DependencyItem_Input()noexcept{}
  
  int DependencyItem_Input::Run(){
    return 0;
  }

  void DependencyItem_Input::DoneEvent(bool IsUpdate){}

  std::pair<bool,uint64_t> DependencyItem_Input::TargetStatus(){
    auto r=FileGetLastUpdateTime(targetPath);
    if(!r.first){
      throw std::runtime_error("DependencyItem_Input: "+targetPath+" 不存在");
    }
    return r;
  }
  

  DependencyItem_SystemProcess::Task_Thread::~Task_Thread(){}

  int DependencyItem_SystemProcess::Task_Thread::Run(std::stringstream& SS,bool ioexclusive){
    return threadCall(SS,ioexclusive);
  }

  DependencyItem_SystemProcess::Task_Process::Task_Process(const std::list<std::string>& Args,IOEncoding io_encoding):args(Args),io_encoding(io_encoding){}

  DependencyItem_SystemProcess::Task_Process::~Task_Process(){}

  int DependencyItem_SystemProcess::Task_Process::Run(std::stringstream& SS,bool ioexclusive){
    H::SystemProcess process;

    auto args=H::Pointer<std::string>::Array(this->args.size());
    auto iterator=this->args.begin();
    for(H::usize i=0,length=args.Length();i<length;i++,iterator++){
      args[i]=*iterator;
    }

    try{
      process.Run(args,!ioexclusive);
      process.WaitStop();
    }catch(const std::exception& e){
      SS<<"\e[" C_VT_F_Red "m任务启动失败\e[0m: "s+e.what()<<std::endl;
      return 1;
    }

    if(!ioexclusive){
      H::Pointer<char> out;
      std::stringstream ss;
      while((out=process.ReadOutput())!=nullptr){
        ss<<std::string(out.GetPointer(),out.Length());
      }
      switch(io_encoding){
        case IOEncoding::Local:
          SS<<H::Local_To_UTF8(ss.str());
          break;
        case IOEncoding::LocalSystem:
          SS<<H::LocalSystem_To_UTF8(ss.str());
          break;
        case IOEncoding::UTF8:
        default:
          SS<<ss.str();
          break;
      }
    }

    return process.GetResult();
  }

  static H::Tree::AVL<std::string,DependencyItem_SystemProcess::Task_Process::IOEncoding> strToIOEncoding={
    {"UTF-8",DependencyItem_SystemProcess::Task_Process::IOEncoding::UTF8},
    {"Local",DependencyItem_SystemProcess::Task_Process::IOEncoding::Local},
    {"LocalSystem",DependencyItem_SystemProcess::Task_Process::IOEncoding::LocalSystem}
  };

  DependencyItem_SystemProcess::Task_Process::IOEncoding DependencyItem_SystemProcess::Task_Process::StringToIOEncoding(const std::string& str){
    auto res=strToIOEncoding.Find(str);
    if(res==strToIOEncoding.end()){
      throw std::invalid_argument(str+" 是无效的 IOEncoding");
    }
    return res->Data();
  }

  DependencyItem_SystemProcess::DependencyItem_SystemProcess(const std::string& TargetPath,const std::list<std::string>& Args,Task_Process::IOEncoding io_encoding,const std::string& RunLog,const std::string& SkipLog,Log::Pointer log)noexcept
    :DependencyItem_TargetPath(TargetPath)
    ,taskList{Task_Process::New(Args,io_encoding)}
    ,runLog(RunLog)
    ,skipLog(SkipLog)
    ,log(log){}
  
  DependencyItem_SystemProcess::DependencyItem_SystemProcess(const std::string& TargetPath,const Task::Pointer& Task,const std::string& RunLog,const std::string& SkipLog,Log::Pointer log)noexcept
    :DependencyItem_TargetPath(TargetPath)
    ,taskList{Task}
    ,runLog(RunLog)
    ,skipLog(SkipLog)
    ,log(log){}

  DependencyItem_SystemProcess::DependencyItem_SystemProcess(const std::string& TargetPath,const std::list<Task::Pointer>& TaskList,const std::string& RunLog,const std::string& SkipLog,Log::Pointer log)noexcept
  :DependencyItem_TargetPath(TargetPath)
  ,taskList(TaskList)
  ,runLog(RunLog)
  ,skipLog(SkipLog)
  ,log(log){}
      
  DependencyItem_SystemProcess::~DependencyItem_SystemProcess()noexcept{
  }

  int DependencyItem_SystemProcess::Run(){
    int r;
    bool ioexclusive;

    std::stringstream ss;

    ioexclusive=IOExclusive();

    if(ioexclusive){
      log->Lock();
      if(runLog.length()>0){
        H::cout<<runLog<<std::endl;
        H::cout.flush();
      }
    }else{
      if(runLog.length()>0){
        ss<<runLog+"\n";
      }
    }

    r=0;
    for(auto& Item:taskList){
      r=Item->Run(ss,ioexclusive);
      if(r!=0){
        break;
      }
    }

    if(ioexclusive){
      log->Unlock();
    }
    
    auto str=ss.str();
    if(str.length()>0){
      log->WriteLog(str,Log::Type::Default);
    }
    return r;
  }

  void DependencyItem_SystemProcess::DoneEvent(bool IsUpdate){
    if(IsUpdate){
      log->WriteLog("",Log::Type::TaskDone);
    }else{
      log->WriteLog(skipLog,Log::Type::TaskDoneSkip);
    }
  }


  DependencyItem_Command::DependencyItem_Command(const std::list<std::string>& Args,Task_Process::IOEncoding io_encoding,const std::string& RunLog,const std::string& SkipLog,Log::Pointer log)noexcept
    :DependencyItem_SystemProcess("",Args,io_encoding,RunLog,SkipLog,log)
    ,isRun(false){}
  
  DependencyItem_Command::DependencyItem_Command(const Task::Pointer& Task,const std::string& RunLog,const std::string& SkipLog,Log::Pointer log)noexcept
    :DependencyItem_SystemProcess("",Task,RunLog,SkipLog,log)
    ,isRun(false){}

  DependencyItem_Command::DependencyItem_Command(const std::list<Task::Pointer>& TaskList,const std::string& RunLog,const std::string& SkipLog,Log::Pointer log)noexcept
    :DependencyItem_SystemProcess("",TaskList,RunLog,SkipLog,log)
    ,isRun(false){}
  
  DependencyItem_Command::~DependencyItem_Command()noexcept{}

  int DependencyItem_Command::Run(){
    auto res=DependencyItem_SystemProcess::Run();
    if(res==0){
      isRun=true;
    }
    return res;
  }

  std::pair<bool,uint64_t> DependencyItem_Command::TargetStatus(){
    if(isRun){
      return {true,UINT64_MAX};
    }
    return {false,0};
  }


  DependencyItem_Directory::Collection::Collection():lock(LockPointer::New()){}

  DependencyChain::Item::Pointer DependencyItem_Directory::Collection::Insert(const H::Path& path,const std::string& RunLog,const std::string& SkipLog,Log::Pointer& log){
    auto res=taskMap.Insert(path,New(path.String(),RunLog,SkipLog,log,lock));
    return res.iterator->Data();
  }

  DependencyItem_Directory::DependencyItem_Directory(const std::string& TargetPath,const std::string& RunLog,const std::string& SkipLog,Log::Pointer& log,const LockPointer& lock)noexcept
    :DependencyItem_TargetPath(TargetPath)
    ,runLog(RunLog)
    ,skipLog(SkipLog)
    ,log(log)
    ,lock(lock){}
  
  DependencyItem_Directory::~DependencyItem_Directory()noexcept{}

  int DependencyItem_Directory::Run(){
    std::pair<int,std::string> res;
    if(lock){
      lock->Lock();
    }
    res=HMake::DirectoryCreate(targetPath);
    if(lock){
      lock->Unlock();
    }
    log->WriteLog(runLog+"\n"+res.second,Log::Type::Default);
    return res.first;
  }

  void DependencyItem_Directory::DoneEvent(bool IsUpdate){
    if(IsUpdate){
      log->WriteLog("",Log::Type::TaskDone);
    }else{
      log->WriteLog(skipLog,Log::Type::TaskDoneSkip);
    }
  }

  std::pair<bool,uint64_t> DependencyItem_Directory::TargetStatus(){
    auto r=FileGetLastUpdateTime(targetPath);
    r.second=0;//文件夹不应该作为是否更新的依据
    return r;
  }

}



